﻿using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;


namespace BizElements.BusinessLayer
{
    /// <summary>
    /// Serializes and deserializes object using XML, SOAP and binary formatters.
    /// </summary>
    public static class Serializer
    {
        #region SOAP formatter.

        /// <summary>
        /// Serializes object with <see cref="System.Runtime.Serialization.Formatters.Soap.SoapFormatter"/>.
        /// </summary>
        /// <param name="obj">Object marked with <see cref="System.SerializableAttribute"/> atribute.</param>
        /// <returns>Serialized object in SOAP format.</returns>
        public static string SerializeWithSoapFormater(object obj)
        {
            if (obj == null)
                return null;

            SoapFormatter formatter = new SoapFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, obj);

            stream.Seek(0, System.IO.SeekOrigin.Begin);
            System.IO.StreamReader reader = new System.IO.StreamReader(stream);
            string serializedObject = reader.ReadToEnd();
            reader.Close();
            stream.Close();

            return serializedObject;
        }

        /// <summary>
        /// Serializes objects with <see cref="System.Runtime.Serialization.Formatters.Soap.SoapFormatter"/>.
        /// </summary>
        /// <param name="objects">Objects marked with <see cref="System.SerializableAttribute"/> atribute.</param>
        /// <returns>Serialized objects in SOAP format.</returns>
        public static string[] SerializeWithSoapFormater(object[] objects)
        {
            string[] serializedObjects = new string[objects.Length];
            for (int idxObject = 0; idxObject < serializedObjects.Length; idxObject++)
                serializedObjects[idxObject] = SerializeWithSoapFormater(objects[idxObject]);

            return serializedObjects;
        }

        /// <summary>
        /// Deserializes SOAP formatted object.
        /// </summary>
        /// <param name="serializedObject">Serialized object in SOAP format.</param>
        /// <returns>Object.</returns>
        public static object DeserializeWithSoapFormater(string serializedObject)
        {
            if (serializedObject == null)
                return null;

            SoapFormatter formatter = new SoapFormatter();
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(serializedObject);
            writer.Flush();

            stream.Seek(0, SeekOrigin.Begin);
            object obj;
            try { obj = formatter.Deserialize(stream); }
            catch { obj = null; }
            stream.Close();

            return obj;
        }

        /// <summary>
        /// Deserializes SOAP formatted objects.
        /// </summary>
        /// <param name="serializedObjects">Serialized objects in SOAP format.</param>
        /// <returns>Objects.</returns>
        public static object[] DeserializeWithSoapFormater(string[] serializedObjects)
        {
            object[] objects = new object[serializedObjects.Length];
            for (int idxObject = 0; idxObject < objects.Length; idxObject++)
                objects[idxObject] = DeserializeWithSoapFormater(serializedObjects[idxObject]);

            return objects;
        }

        #endregion

        #region Binary formatter.

        /// <summary>
        /// Serializes object with <see cref="System.Runtime.Serialization.Formatters.Binary.BinaryFormatter"/>.
        /// </summary>
        /// <param name="obj">Object marked with <see cref="System.SerializableAttribute"/> atribute.</param>
        /// <returns>Serialized object in binary format.</returns>
        public static byte[] SerializeWithBinaryFormater(object obj)
        {
            if (obj == null)
                return null;

            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, obj);

            stream.Seek(0, System.IO.SeekOrigin.Begin);
            byte[] serializedObject = stream.GetBuffer();
            stream.Close();

            return serializedObject;
        }

        /// <summary>
        /// Serializes objects with <see cref="System.Runtime.Serialization.Formatters.Binary.BinaryFormatter"/>.
        /// </summary>
        /// <param name="objects">Objects marked with <see cref="System.SerializableAttribute"/> atribute.</param>
        /// <returns>Serialized objects in binary format.</returns>
        public static byte[][] SerializeWithBinaryFormater(object[] objects)
        {
            byte[][] serializedObjects = new byte[objects.Length][];
            for (int idxObject = 0; idxObject < serializedObjects.Length; idxObject++)
                serializedObjects[idxObject] = SerializeWithBinaryFormater(objects[idxObject]);

            return serializedObjects;
        }

        /// <summary>
        /// Deserializes binary formatted object.
        /// </summary>
        /// <param name="serializedObject">Serialized object in binary format.</param>
        /// <returns>Object.</returns>
        public static object DeserializeWithBinaryFormater(byte[] serializedObject)
        {
            if (serializedObject == null || serializedObject.Length == 0)
                return null;

            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream(serializedObject);
            object obj;
            try { obj = formatter.Deserialize(stream); }
            catch { obj = null; }
            stream.Close();

            return obj;
        }

        /// <summary>
        /// Deserializes binary formatted objecta.
        /// </summary>
        /// <param name="serializedObjects">Serialized objects in binary format.</param>
        /// <returns>Object.</returns>
        public static object[] DeserializeWithBinaryFormater(byte[][] serializedObjects)
        {
            object[] objects = new object[serializedObjects.Length];
            for (int idxObject = 0; idxObject < objects.Length; idxObject++)
                objects[idxObject] = DeserializeWithBinaryFormater(serializedObjects[idxObject]);

            return objects;
        }

        #endregion
    }
}